package com.open4cn.simulator.protocol.xrite;

import cn.hutool.core.util.HexUtil;
import com.open4cn.simulator.core.ext.InMessage;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * @author yinxiaopeng
 * @version 1.0.0
 * @company 致景科技
 * @department 飞梭BU/研发
 * @description
 * @Email yinxiaopeng@zj.tech
 * @date 2022-05-13 00:44
 */
public class Xrite7800Decoder extends ByteToMessageDecoder {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    // 半包-缓存
    private ByteBuf cache = Unpooled.buffer();

    // 触发缓存的次数
    private int cacheTime = 0;

    // 允许触发缓存的最大次数
    private int maxCacheTime = 10;

    private int currentProtocolDataLength = 0;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        cache.writeBytes(in);

        // 报文前5个字节是定义的协议长度
        while (cache.readableBytes() > 5) {
            if (currentProtocolDataLength == 0) {
                currentProtocolDataLength = getProtocolDataLength(cache);
            }
            // 剩余报文必须大于协议长度,才是完整数据
            if (cache.readableBytes() >= currentProtocolDataLength + 1) {
                InMessage xriteInMessage = getMessage(cache, currentProtocolDataLength);
                out.add(xriteInMessage);
                // 重置
                currentProtocolDataLength = 0;
                cache.clear();
            } else {
                if (cacheTime >= maxCacheTime) {
                    cacheTime = 0;
                    currentProtocolDataLength = 0;
                    cache.clear();
                } else {
                    cacheTime++;
                    break;
                }
            }
        }
    }

    /**
     * 构造消息
     *
     * @param cache
     * @param protocolDataLength
     * @return
     */
    private InMessage getMessage(ByteBuf cache, int protocolDataLength) {
        byte[] data = new byte[protocolDataLength];
        cache.readBytes(data);
        InMessage inMessage = new InMessage(data);
        inMessage.setCommand(getCommand(data));
        return inMessage;
    }


    /**
     * 解析协议长度
     * 7e 00 00 00 07
     * 读取前5个字节,00 07就是协议长度
     *
     * @param byteBuf
     * @return
     */
    private int getProtocolDataLength(ByteBuf byteBuf) {
        byte[] headerBytes = new byte[5];
        byteBuf.readBytes(headerBytes);
        String headerStr = HexUtil.encodeHexStr(headerBytes);
        String lengthStr = headerStr.substring(6);
        return Integer.parseInt(lengthStr, 16);
    }

    /**
     * 解析命令字
     *
     * @param msg
     * @return
     */
    private String getCommand(byte[] msg) {
        String hexStr = HexUtil.encodeHexStr(msg);
        return HexUtil.decodeHexStr(hexStr);
    }
}
